package com.zhihui.util;

import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.spec.PKCS8EncodedKeySpec;

import static com.sun.org.apache.xml.internal.security.utils.Base64.decode;

/**
 * 工具类
 *
 * @author Besttone
 *
 */
public class SecuretUtils {

	/**
	 * 加密算法RSA
	 */
	public static final String KEY_ALGORITHM = "RSA";

	/**
	 * RSA最大解密密文大小
	 */
	private static final int MAX_DECRYPT_BLOCK = 128;

	public static char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
			'a', 'b', 'c', 'd', 'e', 'f' };



	/**
	 * 字节数组转为16进制字符串
	 * @param byteArray
	 * @return
	 */
	public static String byteArrayToHex(byte[] byteArray) {
		// 首先初始化一个字符数组，用来存放每个16进制字符
		// new一个字符数组，这个就是用来组成结果字符串的（解释一下：一个byte是八位二进制，也就是2位十六进制字符（2的8次方等于16的2次方））
		char[] resultCharArray = new char[byteArray.length * 2];
		// 遍历字节数组，通过位运算（位运算效率高），转换成字符放到字符数组中去
		int index = 0;
		for (byte b : byteArray) {
			resultCharArray[index++] = hexDigits[b >>> 4 & 0xf];
			resultCharArray[index++] = hexDigits[b & 0xf];
		}
		// 字符数组组合成字符串返回
		return new String(resultCharArray);
	}


	/**
	 * 十六进制表示的字符串转为字节数组
	 * @param s
	 * @return
	 */
	public static byte[] hexStringToByteArray(String s) {
		int len = s.length();
		byte[] b = new byte[len / 2];
		for (int i = 0; i < len; i += 2) {
			// 两位一组，表示一个字节,把这样表示的16进制字符串，还原成一个字节
			b[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character
					.digit(s.charAt(i + 1), 16));
		}
		return b;
	}

	/**
	 * 对字符串进行base64编码
	 * @param str
	 * @return
	 */
	public static String getBase64(String str) {
		byte[] b = null;
		String s = null;
		String s1="";
		try {
			b = str.getBytes("utf-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		if (b != null) {
			s=new String(Base64.encodeBase64(b));
		}
		return s;
	}




	/**
	 * <P>
	 * 私钥解密
	 * </p>
	 *
	 * @param data 已加密数据
	 * @param privateKey 私钥(BASE64编码)
	 * @return
	 * @throws Exception
	 */
	public static String decryptByPrivateKey(String data, String privateKey)
			throws Exception {
		data = data.replace(" ", "+");
		byte[] keyBytes = decode(privateKey);
		PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
		Base64 base64 = new Base64();
		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
		Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
		Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
		cipher.init(Cipher.DECRYPT_MODE, privateK);
		byte[] encryptedData = base64.decode(data);
		int inputLen = encryptedData.length;
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		int offSet = 0;
		byte[] cache;
		int i = 0;
		// 对数据分段解密
		while (inputLen - offSet > 0) {
			if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
				cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
			} else {
				cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
			}
			out.write(cache, 0, cache.length);
			i++;
			offSet = i * MAX_DECRYPT_BLOCK;
		}
		byte[] decryptedData = out.toByteArray();
		out.close();
		return new String(decryptedData);
	}



	/**
	 * 将base64字符串进行解码转换为有效字符串
	 * @param base64Str
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static byte[] releaseBase64(String base64Str) throws UnsupportedEncodingException {

		return Base64.decodeBase64(base64Str.getBytes());
	}


	/**
	 * HMACSHA256进行加密（不可逆）
	 * @param data
	 * @param key 密钥（本地存储）
	 * @return
	 */
	public static byte[] HMACSHA25(byte[] data,byte[] key){
		try  {
			SecretKeySpec signingKey = new SecretKeySpec(key, "HmacSHA256");
			Mac mac = Mac.getInstance("HmacSHA256");
			mac.init(signingKey);
			return mac.doFinal(data);

		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}




	public  static   void  main(String[] args) throws UnsupportedEncodingException {

		String header="{'typ': 'JWT', 'alg': 'HS256'}";
        String base64Header=getBase64(header);
        String payload="{'iss': 'ninghao.net','exp': '1438955445','name': 'wanghao','admin': true}";
		String base64Payload=getBase64(payload);

		String encodedStr=base64Header+"."+base64Payload;

		byte[]  result=HMACSHA25(encodedStr.getBytes(),"secret".getBytes("utf-8"));

		System.out.println(Base64.encodeBase64String(result));

	}

}
